package service

import (
	"bytes"
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"

	"markedit/internal/model"

	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
	"github.com/jung-kurt/gofpdf"
	"github.com/sirupsen/logrus"
	"github.com/unidoc/unioffice/document"
)

type ExportService struct {
	markdownService *MarkdownService
	renderService   *RenderService
	logger          *logrus.Logger
	tempDir         string
}

func NewExportService(markdownService *MarkdownService, renderService *RenderService, logger *logrus.Logger, tempDir string) *ExportService {
	return &ExportService{
		markdownService: markdownService,
		renderService:   renderService,
		logger:          logger,
		tempDir:         tempDir,
	}
}

// ExportToPDF 导出为PDF
func (es *ExportService) ExportToPDF(doc *model.Document, settings map[string]interface{}) ([]byte, error) {
	es.logger.Infof("Starting PDF export for document: %s", doc.ID)

	// 使用gofpdf生成PDF
	pdfData, err := es.generatePDFWithGofpdf(doc, settings)
	if err != nil {
		return nil, fmt.Errorf("failed to generate PDF: %v", err)
	}

	es.logger.Infof("PDF export completed for document: %s", doc.ID)
	return pdfData, nil
}

// ExportToWord 导出为Word文档
func (es *ExportService) ExportToWord(doc *model.Document, settings map[string]interface{}) ([]byte, error) {
	es.logger.Infof("Starting Word export for document: %s", doc.ID)

	// 创建Word文档
	wordDoc := document.New()

	// 添加标题
	if doc.Title != "" {
		para := wordDoc.AddParagraph()
		run := para.AddRun()
		run.AddText(doc.Title)
		run.Properties().SetBold(true)
		run.Properties().SetSize(16)
	}

	// 处理Markdown内容
	err := es.processMarkdownToWord(wordDoc, doc.Content)
	if err != nil {
		return nil, fmt.Errorf("failed to process markdown content: %v", err)
	}

	// 保存到字节数组
	var buf bytes.Buffer
	err = wordDoc.Save(&buf)
	if err != nil {
		return nil, fmt.Errorf("failed to save word document: %v", err)
	}

	es.logger.Infof("Word export completed for document: %s", doc.ID)
	return buf.Bytes(), nil
}

// ExportToHTML 导出为HTML
func (es *ExportService) ExportToHTML(doc *model.Document, settings map[string]interface{}) ([]byte, error) {
	es.logger.Infof("Starting HTML export for document: %s", doc.ID)

	// 渲染Markdown为HTML
	htmlContent, err := es.markdownService.RenderToHTML(doc.Content)
	if err != nil {
		return nil, fmt.Errorf("failed to render markdown: %v", err)
	}

	// 处理图表渲染
	htmlContent, err = es.processChartsForHTML(htmlContent)
	if err != nil {
		return nil, fmt.Errorf("failed to process charts: %v", err)
	}

	// 创建完整的HTML页面
	fullHTML := es.createFullHTMLPage(doc.Title, htmlContent)

	es.logger.Infof("HTML export completed for document: %s", doc.ID)
	return []byte(fullHTML), nil
}

// generatePDFWithChrome 使用Chrome生成PDF
func (es *ExportService) generatePDFWithChrome(htmlContent string, settings map[string]interface{}) ([]byte, error) {
	// 创建临时HTML文件
	tempFile := filepath.Join(es.tempDir, fmt.Sprintf("export_%d.html", time.Now().UnixNano()))
	err := ioutil.WriteFile(tempFile, []byte(htmlContent), 0644)
	if err != nil {
		return nil, err
	}
	defer os.Remove(tempFile)

	// 创建Chrome上下文
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// 设置超时
	ctx, cancel = context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	var pdfData []byte

	// 生成PDF
	err = chromedp.Run(ctx,
		chromedp.Navigate("file://"+tempFile),
		chromedp.WaitVisible("body"),
		chromedp.ActionFunc(func(ctx context.Context) error {
			buf, _, err := page.PrintToPDF().
				WithPrintBackground(true).
				WithPaperWidth(8.27).   // A4 width in inches
				WithPaperHeight(11.7).  // A4 height in inches
				WithMarginTop(0.4).
				WithMarginBottom(0.4).
				WithMarginLeft(0.4).
				WithMarginRight(0.4).
				Do(ctx)
			if err != nil {
				return err
			}
			pdfData = buf
			return nil
		}),
	)

	if err != nil {
		return nil, err
	}

	return pdfData, nil
}

// generatePDFWithGofpdf 使用gofpdf生成PDF
func (es *ExportService) generatePDFWithGofpdf(doc *model.Document, settings map[string]interface{}) ([]byte, error) {
	// 创建PDF实例
	pdf := gofpdf.New("P", "mm", "A4", "")
	pdf.AddPage()
	
	// 设置字体（使用内置字体）
	pdf.SetFont("Arial", "B", 16)
	
	// 添加标题
	if doc.Title != "" {
		pdf.Cell(0, 10, doc.Title)
		pdf.Ln(15)
	}
	
	// 设置正文字体
	pdf.SetFont("Arial", "", 12)
	
	// 处理Markdown内容
	content := es.processMarkdownForPDF(doc.Content)
	
	// 分行处理内容
	lines := strings.Split(content, "\n")
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			pdf.Ln(5)
			continue
		}
		
		// 处理不同类型的行
		if strings.HasPrefix(line, "# ") {
			pdf.SetFont("Arial", "B", 14)
			pdf.Cell(0, 8, strings.TrimPrefix(line, "# "))
			pdf.Ln(10)
			pdf.SetFont("Arial", "", 12)
		} else if strings.HasPrefix(line, "## ") {
			pdf.SetFont("Arial", "B", 13)
			pdf.Cell(0, 7, strings.TrimPrefix(line, "## "))
			pdf.Ln(8)
			pdf.SetFont("Arial", "", 12)
		} else if strings.HasPrefix(line, "### ") {
			pdf.SetFont("Arial", "B", 12)
			pdf.Cell(0, 6, strings.TrimPrefix(line, "### "))
			pdf.Ln(7)
			pdf.SetFont("Arial", "", 12)
		} else {
			// 普通文本，处理长行自动换行
			pdf.MultiCell(0, 6, line, "", "", false)
			pdf.Ln(2)
		}
	}
	
	// 生成PDF字节数据
	var buf bytes.Buffer
	err := pdf.Output(&buf)
	if err != nil {
		return nil, err
	}
	
	return buf.Bytes(), nil
}

// processMarkdownForPDF 处理Markdown内容用于PDF生成
func (es *ExportService) processMarkdownForPDF(content string) string {
	// 移除一些Markdown语法，保留基本格式
	content = strings.ReplaceAll(content, "**", "")
	content = strings.ReplaceAll(content, "*", "")
	content = strings.ReplaceAll(content, "`", "")
	
	// 处理链接格式 [text](url) -> text
	linkRegex := `\[([^\]]+)\]\([^)]+\)`
	content = strings.ReplaceAll(content, linkRegex, "$1")
	
	return content
}

// processChartsForPDF 处理图表用于PDF导出
func (es *ExportService) processChartsForPDF(htmlContent string) (string, error) {
	// 查找Mermaid图表
	htmlContent = es.processMermaidCharts(htmlContent)
	
	// 查找PlantUML图表
	htmlContent = es.processPlantUMLCharts(htmlContent)

	return htmlContent, nil
}

// processChartsForHTML 处理图表用于HTML导出
func (es *ExportService) processChartsForHTML(htmlContent string) (string, error) {
	// 对于HTML导出，保持原有的图表代码，让前端JavaScript处理
	return htmlContent, nil
}

// processMermaidCharts 处理Mermaid图表
func (es *ExportService) processMermaidCharts(htmlContent string) string {
	// 查找所有Mermaid代码块
	mermaidStart := "```mermaid"
	mermaidEnd := "```"
	
	for {
		startIdx := strings.Index(htmlContent, mermaidStart)
		if startIdx == -1 {
			break
		}
		
		endIdx := strings.Index(htmlContent[startIdx+len(mermaidStart):], mermaidEnd)
		if endIdx == -1 {
			break
		}
		endIdx += startIdx + len(mermaidStart)
		
		// 提取Mermaid代码
		mermaidCode := htmlContent[startIdx+len(mermaidStart):endIdx]
		mermaidCode = strings.TrimSpace(mermaidCode)
		
		// 渲染为图片
		imgData, err := es.renderService.RenderMermaidToImage(mermaidCode, map[string]interface{}{
			"format": "png",
			"dpi":    300,
		})
		if err != nil {
			es.logger.Warnf("Failed to render Mermaid chart: %v", err)
			continue
		}
		
		// 替换为img标签
		imgTag := fmt.Sprintf(`<img src="data:image/png;base64,%s" alt="Mermaid Chart" style="max-width: 100%;">`, imgData)
		htmlContent = htmlContent[:startIdx] + imgTag + htmlContent[endIdx+len(mermaidEnd):]
	}
	
	return htmlContent
}

// processPlantUMLCharts 处理PlantUML图表
func (es *ExportService) processPlantUMLCharts(htmlContent string) string {
	// 查找所有PlantUML代码块
	plantumlStart := "```plantuml"
	plantumlEnd := "```"
	
	for {
		startIdx := strings.Index(htmlContent, plantumlStart)
		if startIdx == -1 {
			break
		}
		
		endIdx := strings.Index(htmlContent[startIdx+len(plantumlStart):], plantumlEnd)
		if endIdx == -1 {
			break
		}
		endIdx += startIdx + len(plantumlStart)
		
		// 提取PlantUML代码
		plantumlCode := htmlContent[startIdx+len(plantumlStart):endIdx]
		plantumlCode = strings.TrimSpace(plantumlCode)
		
		// 渲染为图片
		imgData, err := es.renderService.RenderPlantUMLToImage(plantumlCode, map[string]interface{}{
			"format": "png",
			"dpi":    300,
		})
		if err != nil {
			es.logger.Warnf("Failed to render PlantUML chart: %v", err)
			continue
		}
		
		// 替换为img标签
		imgTag := fmt.Sprintf(`<img src="data:image/png;base64,%s" alt="PlantUML Chart" style="max-width: 100%;">`, imgData)
		htmlContent = htmlContent[:startIdx] + imgTag + htmlContent[endIdx+len(plantumlEnd):]
	}
	
	return htmlContent
}

// processMarkdownToWord 处理Markdown内容到Word文档
func (es *ExportService) processMarkdownToWord(wordDoc *document.Document, content string) error {
	// 简单的Markdown到Word转换
	// 这里可以根据需要实现更复杂的转换逻辑
	
	lines := strings.Split(content, "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		
		para := wordDoc.AddParagraph()
		run := para.AddRun()
		
		// 处理标题
		if strings.HasPrefix(line, "# ") {
			run.AddText(strings.TrimPrefix(line, "# "))
			run.Properties().SetBold(true)
			run.Properties().SetSize(14)
		} else if strings.HasPrefix(line, "## ") {
			run.AddText(strings.TrimPrefix(line, "## "))
			run.Properties().SetBold(true)
			run.Properties().SetSize(12)
		} else if strings.HasPrefix(line, "### ") {
			run.AddText(strings.TrimPrefix(line, "### "))
			run.Properties().SetBold(true)
			run.Properties().SetSize(11)
		} else {
			run.AddText(line)
		}
	}
	
	return nil
}

// createFullHTMLPage 创建完整的HTML页面
func (es *ExportService) createFullHTMLPage(title, content string) string {
	return fmt.Sprintf(`
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>%s</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        h1, h2, h3, h4, h5, h6 {
            margin-top: 24px;
            margin-bottom: 16px;
            font-weight: 600;
            line-height: 1.25;
        }
        h1 { font-size: 2em; border-bottom: 1px solid #eaecef; padding-bottom: 10px; }
        h2 { font-size: 1.5em; }
        h3 { font-size: 1.25em; }
        code {
            background-color: #f6f8fa;
            border-radius: 3px;
            font-size: 85%%;
            margin: 0;
            padding: 0.2em 0.4em;
        }
        pre {
            background-color: #f6f8fa;
            border-radius: 6px;
            font-size: 85%%;
            line-height: 1.45;
            overflow: auto;
            padding: 16px;
        }
        blockquote {
            border-left: 4px solid #dfe2e5;
            margin: 0;
            padding: 0 16px;
            color: #6a737d;
        }
        table {
            border-collapse: collapse;
            width: 100%%;
        }
        th, td {
            border: 1px solid #dfe2e5;
            padding: 6px 13px;
            text-align: left;
        }
        th {
            background-color: #f6f8fa;
            font-weight: 600;
        }
        img {
            max-width: 100%%;
            height: auto;
        }
    </style>
</head>
<body>
    %s
</body>
</html>`, title, content)
}